package jmine.tec.aom.services;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import jmine.tec.aom.AOMMessages;
import jmine.tec.aom.domain.Propertized;
import jmine.tec.aom.domain.Property;
import jmine.tec.aom.exception.FillException;
import jmine.tec.aom.util.PropertyValueUtils;
import jmine.tec.di.annotation.Injected;
import jmine.tec.services.annotations.SuffixOf;
import jmine.tec.services.api.ServiceExecutionException;
import bancosys.tec.exception.LocalizedMessageHolder;

/**
 * Base class for services that want to add multiple {@link jmine.tec.aom.domain.AbstractPropertyValue} to a {@link Propertized}.
 * 
 * @author jrenaut
 */
public abstract class AbstractPropertyValueService {

    public static final String PROPERTY_VALUE_PREFIX = "Property ";

    private PropertyValueUtils propertyValueUtils;

    private Map<String, String> propertyValues = new HashMap<String, String>();

    /**
     * @param propertized a {@link Propertized}
     * @param identification an identification for this {@link Propertized} should an error occur
     * @throws ServiceExecutionException if a specified {@link Property} is not valid for this {@link Propertized}
     */
    protected final void addPropertyValues(Propertized propertized, String identification) throws ServiceExecutionException {
        for (Entry<String, String> entry : this.getPropertyValues().entrySet()) {
            if (entry.getValue() == null) {
                continue;
            }

            String propertyName = entry.getKey();
            Property property = propertized.getPropertyByName(propertyName);

            if (property == null) {
                throw new ServiceExecutionException(AOMMessages.PROPERTY_NOT_FOUND_FOR_PROPERTIZED.create(propertyName, identification));
            }

            try {
                propertized.addPropertyValue(this.getPropertyValueUtils().createPropertyValue(property, entry.getValue()));
            } catch (FillException e) {
                LocalizedMessageHolder holder = AOMMessages.INVALID_PROPERTY_VALUE.create(propertyName, identification, entry.getValue());
                throw new ServiceExecutionException(holder);
            }
        }
    }

    /**
     * @return the propertyValueUtils
     */
    protected PropertyValueUtils getPropertyValueUtils() {
        return this.propertyValueUtils;
    }

    /**
     * @return the propertyValues
     */
    protected Map<String, String> getPropertyValues() {
        return this.propertyValues;
    }

    /**
     * @param propertyValueUtils the propertyValueUtils to set
     */
    @Injected
    public void setPropertyValueUtils(PropertyValueUtils propertyValueUtils) {
        this.propertyValueUtils = propertyValueUtils;
    }

    /**
     * @param propertyValues the propertyValues to set
     */
    @SuffixOf(preffix = PROPERTY_VALUE_PREFIX)
    public void setPropertyValues(Map<String, String> propertyValues) {
        this.propertyValues.putAll(propertyValues);
    }
}
